package cn.sunxiansheng.redis.utils;

import org.springframework.data.redis.core.RedisTemplate;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * Description: Redis的List类型操作
 *
 * @Author sun
 * @Create 2024/11/14 14:50
 * @Version 1.0
 */
public class RList extends RBase {

    /**
     * 构造器给父类注入RedisTemplate
     *
     * @param redisTemplate RedisTemplate实例
     */
    public RList(RedisTemplate<String, Object> redisTemplate) {
        super(redisTemplate);
    }

    /**
     * 左侧添加单个值
     *
     * @param key   键
     * @param value 要添加的值
     * @return 添加后的List长度
     */
    public Long leftPush(String key, Object value) {
        return redisTemplate.opsForList().leftPush(key, value);
    }

    /**
     * 左侧批量添加多个值（使用List参数方式）
     *
     * @param key      键
     * @param dataList 要添加的值列表
     * @param <V>      值类型
     * @return 添加后的List长度，调用方可以忽略返回值
     */
    public <V> Long leftPushAll(String key, List<V> dataList) {
        return redisTemplate.opsForList().leftPushAll(key, dataList.toArray());
    }

    /**
     * 左侧批量添加多个值（使用Collection参数方式）
     *
     * @param key           键
     * @param dataCollection 要添加的值集合
     * @param <V>           值类型
     * @return 添加后的List长度
     */
    public <V> Long leftPushAll(String key, Collection<V> dataCollection) {
        return redisTemplate.opsForList().leftPushAll(key, dataCollection.toArray());
    }

    /**
     * 右侧添加单个值
     *
     * @param key   键
     * @param value 要添加的值
     * @return 添加后的List长度
     */
    public Long rightPush(String key, Object value) {
        return redisTemplate.opsForList().rightPush(key, value);
    }

    /**
     * 右侧批量添加多个值（使用List参数方式）
     *
     * @param key      键
     * @param dataList 要添加的值列表
     * @param <V>      值类型
     * @return 添加后的List长度
     */
    public <V> Long rightPushAll(String key, List<V> dataList) {
        return redisTemplate.opsForList().rightPushAll(key, dataList.toArray());
    }

    /**
     * 右侧批量添加多个值（使用Collection参数方式）
     *
     * @param key           键
     * @param dataCollection 要添加的值集合
     * @param <V>           值类型
     * @return 添加后的List长度
     */
    public <V> Long rightPushAll(String key, Collection<V> dataCollection) {
        return redisTemplate.opsForList().rightPushAll(key, dataCollection.toArray());
    }

    /**
     * 根据值移除指定数量的匹配元素
     *
     * @param key   键
     * @param count 要移除的元素数量
     * @param value 要移除的值
     * @return 移除的元素数量
     */
    public Long removeByValue(String key, long count, Object value) {
        return redisTemplate.opsForList().remove(key, count, value);
    }

    /**
     * 从右侧弹出元素并转换为指定类型
     *
     * @param key  键
     * @param type 期望的返回值类型
     * @param <T>  泛型，表示期望的返回类型
     * @return 弹出并转换后的元素
     */
    public <T> T popRight(String key, Class<T> type) {
        Object value = redisTemplate.opsForList().rightPop(key);
        return convertValue(value, type);
    }

    /**
     * 从左侧弹出元素并转换为指定类型
     *
     * @param key  键
     * @param type 期望的返回值类型
     * @param <T>  泛型，表示期望的返回类型
     * @return 弹出并转换后的元素
     */
    public <T> T popLeft(String key, Class<T> type) {
        Object value = redisTemplate.opsForList().leftPop(key);
        return convertValue(value, type);
    }

    /**
     * 根据索引设置List中的值
     *
     * @param key   键
     * @param index 索引位置，从0开始
     * @param value 设置的值
     */
    public void set(String key, final long index, Object value) {
        redisTemplate.opsForList().set(key, index, value);
    }

    /**
     * 获取List中的所有数据，并将每个元素转换为指定类型
     *
     * @param key  键
     * @param type 要转换的值类型
     * @param <T>  要转换的值类型
     * @return 转换后的List
     */
    public <T> List<T> rangeAll(String key, Class<T> type) {
        List<Object> range = redisTemplate.opsForList().range(key, 0, -1);
        List<T> result = new ArrayList<>();

        if (range != null) {
            for (Object item : range) {
                result.add(convertValue(item, type));
            }
        }
        return result;
    }

    /**
     * 根据索引获取List中的元素并转换为指定类型
     *
     * @param key   键
     * @param index 索引位置，从0开始
     * @param type  期望的返回值类型
     * @param <T>   泛型，表示期望的返回类型
     * @return 转换后的元素
     */
    public <T> T getElementByIndex(String key, long index, Class<T> type) {
        Object value = redisTemplate.opsForList().index(key, index);
        return convertValue(value, type);
    }

    /**
     * 获取List的长度
     *
     * @param key 键
     * @return List的长度
     */
    public Long size(String key) {
        return redisTemplate.opsForList().size(key);
    }
}